package com.zonski.jbots.wireless.client;

import com.zonski.jbots.engine.Room;
import com.zonski.jbots.engine.Engine;
import com.zonski.jbots.engine.Entity;
import com.zonski.jbots.engine.QuickVector;
import com.zonski.jbots.engine.entity.AbstractMind;
import com.zonski.jbots.game.JBotsGameController;
import com.zonski.jbots.game.JBotsConstants;
import com.zonski.jbots.game.resources.EggMaker;

import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import java.util.Vector;
import java.io.IOException;

/**
 * Created by IntelliJ IDEA.
 * User: Chris Glover
 * Date: Oct 29, 2003
 * Time: 10:46:10 AM
 * To change this template use Options | File Templates.
 */
public class JBotsGameCanvas extends GameCanvas
{
    private static final Font INSTRUCTION_FONT = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
    private static final Font TITLE_FONT = Font.getDefaultFont();
    private static final Font INFO_FONT = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
    private static final int RECT_WIDTH = 64;
    private static final int RECT_HEIGHT = 5;

    public static final String GAME_OVER_KEY        = "game_over";
    public static final String LOADING_KEY          = "loading";
    public static final String DEMO_KEY             = "demo";
    public static final String LEVEL_KEY            = "level";
    public static final String FIRE_TO_PLAY_KEY     = "fire_to_play";
    public static final String EGG_INSTRUCTION_KEY  = "egg_instruction";
    public static final String SHOOT_INSTRUCTION_KEY= "shoot_instruction";
    public static final String BOMB_INSTRUCTION_KEY = "bomb_instruction";
    public static final String MOVE_INSTRUCTION_KEY = "move_instruction";

    private static final String FORMAT_REPLACE = "{0}";

    public static final String MICROEDITION_LOCALE  = "microedition.locale";

    public static final String getString(String key, MIDlet midlet)
    {
        String locale = midlet.getAppProperty(MICROEDITION_LOCALE);
        if(locale == null)
        {
            locale = System.getProperty(MICROEDITION_LOCALE);
        }
        // try the full locale
        String result = null;
        if(locale != null)
        {
            String localeKey = key + "." + locale;
            result = midlet.getAppProperty(localeKey);
            if(result == null)
            {
                // try trimming the locale to just the language name
                int index = locale.lastIndexOf('_');
                if(index >= 0)
                {
                    localeKey = key + "." + locale.substring(0, index);
                    result = midlet.getAppProperty(localeKey);
                }
            }
        }
        if(result == null)
        {
            // try getting the key directly
            result = midlet.getAppProperty(key);
        }
        if(result == null)
        {
            // use the key!!!
            result = key;
        }
        return result;
    }

    public static final String format(String f, String val)
    {
        String result;
        int index = f.indexOf(FORMAT_REPLACE);
        if(index >= 0)
        {
            StringBuffer sb = new StringBuffer(f);
            sb.delete(index, index + FORMAT_REPLACE.length());
            sb.insert(index, val);
            result = sb.toString();
        }else{
            result = f;
        }
        return result;
    }

    private Image introImage;

    private RoomRenderer roomRenderer;
    private JBotsGameController controller;

    private int offsetX;
    private int offsetY;

    private AbstractMind player1Mind;
    private AbstractMind player2Mind;
    private AbstractMind player3Mind;
    private AbstractMind player4Mind;

    private String gameOverString;
    private String loadingString;
    private String demoString;
    private String levelString;
    private String fireToPlayString;

    private String shootInstructionString;
    private String eggInstructionString;
    private String bombInstructionString;

    public int shakeCycles;

    public JBotsGameCanvas(JBotsGameController controller, MIDlet midlet)
    {
        super(true);
        this.controller = controller;

        this.gameOverString = getString(GAME_OVER_KEY, midlet);
        this.loadingString = getString(LOADING_KEY, midlet);
        this.demoString = getString(DEMO_KEY, midlet);
        this.levelString = getString(LEVEL_KEY, midlet);
        this.fireToPlayString = getString(FIRE_TO_PLAY_KEY, midlet);

        this.shootInstructionString = format(getString(SHOOT_INSTRUCTION_KEY, midlet),
                this.getKeyName(getKeyCode(GameCanvas.GAME_A)));
        this.bombInstructionString = format(getString(BOMB_INSTRUCTION_KEY, midlet),
                this.getKeyName(getKeyCode(GameCanvas.GAME_B)));
        this.eggInstructionString = format(getString(EGG_INSTRUCTION_KEY, midlet),
                this.getKeyName(getKeyCode(GameCanvas.FIRE)));

        this.player1Mind = (AbstractMind)controller.getEngine().getMind(Engine.getPlayerMindName(0));
        this.player2Mind = (AbstractMind)controller.getEngine().getMind(Engine.getPlayerMindName(1));
        this.player3Mind = (AbstractMind)controller.getEngine().getMind(Engine.getPlayerMindName(2));
        this.player4Mind = (AbstractMind)controller.getEngine().getMind(Engine.getPlayerMindName(3));
    }

    public void setRoomRenderer(RoomRenderer roomRenderer)
    {
        this.roomRenderer = roomRenderer;
    }

    public void draw()
    {
        try
        {
            Graphics g = this.getGraphics();
            g.setColor(100, 100, 100);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());

            if(this.shakeCycles > 0)
            {
                int dx = (this.shakeCycles % 5) - 2;
                int dy = (this.shakeCycles / 2) % 5 - 2;
                g.translate(dx, dy);
                this.shakeCycles--;
            }

            switch(this.controller.getMode())
            {
                case JBotsGameController.DEMO:
                case JBotsGameController.GAME:
                case JBotsGameController.GAME_OVER:
                case JBotsGameController.PRE_LEVEL:
                    if(this.roomRenderer != null)
                    {
                        Room room = this.controller.getEngine().getRoom();
                        String title = room.getName();

                        if(title != null)
                        {
                            g.setFont(TITLE_FONT);
                            g.setColor(200, 200, 200);
                            g.drawString(title, this.getWidth()/2, 0, Graphics.HCENTER | Graphics.TOP);
                        }

                        int width = room.getWidth();
                        int height = room.getHeight();
                        int tx = (this.getWidth() - width)/2 + offsetX;
                        int ty = this.getHeight() - height - RECT_HEIGHT*2 - 1 + offsetY;

                        this.drawPlayer(g, player1Mind, tx, ty - 2*RECT_HEIGHT, 0, 255, 255, true);
                        this.drawPlayer(g, player2Mind, tx + width - RECT_WIDTH, ty - 2*RECT_HEIGHT, 255, 0, 0, false);
                        this.drawPlayer(g, player3Mind, tx, ty + height + RECT_HEIGHT, 255, 255, 0, false);
                        this.drawPlayer(g, player4Mind, tx + width - RECT_WIDTH, ty + height + RECT_HEIGHT, 255, 0, 255, false);


                        if(tx > 0 && ty > 0)
                        {
                            g.translate(tx, ty);
                        }

                        this.roomRenderer.render(g, room);
                        String text = null;

                        if(controller.getMode() == JBotsGameController.DEMO)
                        {
                            text = this.demoString;
                        }else if(controller.getMode() == JBotsGameController.GAME_OVER){
                            text = this.gameOverString;
                        }else if(controller.getMode() == JBotsGameController.PRE_LEVEL){
                            text = this.levelString+" "+Integer.toString(controller.getLevel()+1);
                        }


                        if(tx > 0 && ty > 0)
                        {
                            g.translate(-tx, -ty);
                        }

                        if(text != null)
                        {
                            g.setFont(INFO_FONT);
                            g.setColor(255, 255, 255);
                            g.drawString(text, this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER | Graphics.BASELINE);
                        }
                    }
                    break;
                case JBotsGameController.LOADING:
                case JBotsGameController.GAME_START:
                    g.setColor(255, 255, 255);
                    g.setFont(INFO_FONT);
                    g.drawString(this.loadingString,
                            getWidth()/2, getHeight()/2,
                            Graphics.HCENTER | Graphics.BASELINE);
                    break;
                case JBotsGameController.INTRO:
                    // render intro image (it's gay)
                    if(this.introImage == null)
                    {
                        Image image = Image.createImage("/images/jbots.png");
                        // expand the intro image to fit the screen size

                        int width = this.getWidth();
                        int height = this.getHeight();
                        Image introImage = Image.createImage(width, height);
                        Graphics introGraphics = introImage.getGraphics();
                        int y = (height - image.getHeight())/2;
                        for(int x=0; x<(width - image.getWidth())/2 + 1; x++)
                        {
                            introGraphics.drawImage(image, x, y, Graphics.TOP | Graphics.LEFT);
                            introGraphics.drawImage(image, (width + image.getWidth())/2 + x, y, Graphics.TOP | Graphics.LEFT);
                        }
                        introGraphics.drawImage(image, width/2, y, Graphics.TOP | Graphics.HCENTER);
                        int dl = (height - image.getHeight())/2;
                        for(int dy = 0; dy < dl + 1; dy++)
                        {
                            int iy = y + image.getHeight() + dy;
                            introGraphics.setClip(0, iy, width, 1);
                            introGraphics.drawImage(introImage, 0, iy + 1, Graphics.BOTTOM | Graphics.LEFT);
                            int uy = y - dy - 1;
                            introGraphics.setClip(0, uy, width, 1);
                            introGraphics.drawImage(introImage, 0, uy - dl, Graphics.TOP | Graphics.LEFT);
                        }
                        this.introImage = Image.createImage(introImage);
                    }
                    g.drawImage(this.introImage, getWidth()/2, 0, Graphics.TOP | Graphics.HCENTER);
                    g.setColor(0, 0, 0);
                    g.setFont(INFO_FONT);
                    // TODO : intro screen
                    int y = (getHeight() + INFO_FONT.getHeight())/2;
                    int x = getWidth()/2;
                    int align = Graphics.HCENTER | Graphics.BASELINE;
                    g.drawString(this.fireToPlayString, x, y, align);
                    y += INFO_FONT.getHeight();
                    g.setFont(INSTRUCTION_FONT);
                    g.drawString(this.eggInstructionString, x, y, align);
                    y += INSTRUCTION_FONT.getHeight();
                    g.drawString(this.shootInstructionString, x, y, align);
                    y += INSTRUCTION_FONT.getHeight();
                    g.drawString(this.bombInstructionString, x, y, align);
                    break;
            }
            this.flushGraphics();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    public final void setOffset(int x, int y)
    {
        this.offsetX = x;
        this.offsetY = y;
    }

    private final void drawPlayer(Graphics g, AbstractMind mind, int x, int y, int rd, int gn, int bl, boolean status)
    {
        if(mind.getEntity() != null)
        {
            Entity entity = mind.getEntity();
            int fulllength = (RECT_WIDTH * entity.getMaxCharge()) / JBotsConstants.MAX_CHARGE;

            if(entity.getCharge() <= 0)
            {
                g.setColor(128, 128, 128);
            }else{
                int length = (fulllength * entity.getCharge())/entity.getMaxCharge();
                g.setColor(rd, gn, bl);
                g.fillRect(x, y, length, RECT_HEIGHT);

                if(status)
                {
                    QuickVector resources = entity.getResources();
                    EggMaker currentEggMaker = null;
                    for(int i=0; i<resources.size(); i++)
                    {
                        Object resource = resources.elementAt(i);
                        if(resource instanceof EggMaker)
                        {
                            EggMaker eggMaker = (EggMaker)resource;
                            if(eggMaker.getCharge() > 0 &&
                               (currentEggMaker == null || eggMaker.getCharge() > currentEggMaker.getCharge()))
                            {
                                currentEggMaker = eggMaker;
                            }
                        }
                    }
                    if(currentEggMaker != null)
                    {
                        if(currentEggMaker.getToCreate() != null)
                        {
                            Sprite sprite = this.roomRenderer.getSprite(currentEggMaker.getToCreate());
                            sprite.setPosition(x, y - sprite.getHeight() - 2);
                            sprite.paint(g);
                        }

                        // draw the status
                        if(currentEggMaker.getCharge() == currentEggMaker.getMaxCharge())
                        {
                            g.setColor(0, 255, 0);
                        }else if(currentEggMaker.getCharge() >= currentEggMaker.getMinCharge()){
                            g.setColor(255, 255, 0);
                        }else{
                            g.setColor(255, 0, 0);
                        }
                        int cw = (fulllength * currentEggMaker.getCharge()) / entity.getMaxCharge();
                        g.fillRect(x, y, cw, RECT_HEIGHT);

                        g.setColor(255, 0, 0);
                        int lw = (fulllength * currentEggMaker.getMinCharge())/entity.getMaxCharge();
                        g.drawLine(x+lw, y, x+lw, y+RECT_HEIGHT-1);

                        g.setColor(0, 255, 0);
                        int mw = (fulllength * currentEggMaker.getMaxCharge())/entity.getMaxCharge();
                        g.drawLine(x+mw, y, x+mw, y+RECT_HEIGHT-1);
                    }
                }
                g.setColor(255, 255, 255);
            }
            g.drawRect(x, y, fulllength-1, RECT_HEIGHT-1);
        }
    }
}
